package trb.complexshield.benchmarking;

import com.sun.j3d.loaders.Scene;
import java.io.File;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Node;
import no.hrp.hvrc.rad.dosim.bvh.BottumUpBVH;
import no.hrp.hvrc.utils.j3d.BBox;
import no.hrp.hvrc.utils.j3d.GeometryExtractor;
import no.hrp.hvrc.utils.j3d.Mat4;
import no.hrp.hvrc.utils.j3d.ObjectViewer;
import no.hrp.hvrc.utils.j3d.PluggableLoader;
import no.hrp.hvrc.utils.j3d.SGUtils;
import no.hrp.hvrc.utils.j3d.Vec3;
import no.hrp.hvrc.utils.j3d.boundingbox.BoundingBoxHelper;
import trb.complexshield.ComplexShield;
import trb.complexshield.bool.ComplexShieldSegmentsProducer;
import trb.complexshield.bool.model.AABBCreator;
import trb.complexshield.bool.model.BoolBox;
import trb.complexshield.bool.model.BoolCylinder;
import trb.complexshield.bool.model.BoolOr;
import trb.complexshield.bool.model.BoolSubtract;
import trb.complexshield.bool.model.DistanceCreator;
import trb.complexshield.bool.model.SegmentsCreator;
import trb.complexshield.bool.visualisation.DistanceVisualisation;
import trb.complexshield.closedmesh.BvhCollisionMesh;
import trb.complexshield.closedmesh.ClosedMesh;
import trb.complexshield.voxel.VoxelFromBool;
import trb.complexshield.voxel.VoxelGridBox;

public class BenchmarkTub {

    public static final String PATH = "./data/tub.wrl";

    public static void main(String[] args) {
        try {
            Object boolModel = createBoolModel();
            VoxelGridBox voxelGridBox = VoxelFromBool.createVoxel(boolModel, 20);
            DistanceVisualisation distanceVisualisation = new DistanceVisualisation(
                    AABBCreator.createAABB(boolModel), DistanceCreator.createDistanceProducer(boolModel));

            BranchGroup branchGroup = SGUtils.wrapInBrancGroup(
                    //distanceVisualisation.update(),
                    createJava3DModel()
                    //new VoxelVisualisation(voxelGridBox, boolModel).rootBG
            );

            ObjectViewer.view(branchGroup);
        } catch (Exception ex) {
            ex.printStackTrace();
            System.exit(0);
        }
    }

    public static ComplexShield createBool() {
        Object boolModel = createBoolModel();
        BottumUpBVH.AABB aabb = new BottumUpBVH.AABB(AABBCreator.createAABB(boolModel));
        return new ComplexShieldSegmentsProducer(SegmentsCreator.createSegmentsProducer(boolModel), aabb);
    }

    public static ComplexShield createComplexShieldFromBoolModel(Object boolModel) {
        BottumUpBVH.AABB aabb = new BottumUpBVH.AABB(AABBCreator.createAABB(boolModel));
        return new ComplexShieldSegmentsProducer(SegmentsCreator.createSegmentsProducer(boolModel), aabb);
    }

    public static Object createBoolModel() {
        BoolBox innerBox = new BoolBox(new Vec3(-1, 0.1f, -1), new Vec3(1, 1, 1), new Mat4());
        BoolCylinder innerCylinder = new BoolCylinder(1f, 1f, new Mat4().translate(-1f, 0.1f, 0));
        BoolOr inner = new BoolOr(innerBox, innerCylinder);

        BoolBox outerBox = new BoolBox(new Vec3(-1f, 0f, -1.5f), new Vec3(1.5f, 1, 1.5f), new Mat4());
        BoolCylinder outerCylinder = new BoolCylinder(1.5f, 1f, new Mat4().translate(-1f, 0f, 0));
        BoolOr outer = new BoolOr(outerBox, outerCylinder);

        return new BoolSubtract(outer, inner);
    }

    public static ClosedMesh createClosedMesh() {
        return createClosedMesh(loadVrml(PATH).getSceneGroup());
    }

    public static ClosedMesh createClosedMesh(Node node) {
        try {
            GeometryExtractor geometryExtractor = GeometryExtractor.extractInWorldSpace(node);
            return new ClosedMesh(geometryExtractor.getCoords(), geometryExtractor.getIndices(), new Mat4());
        } catch (Exception ex) {
            ex.printStackTrace();
            throw new RuntimeException("Failed to load tub model");
        }
    }

    public static BvhCollisionMesh createBvhMesh() {
        return createBvhMesh(createJava3DModel());
    }

    public static BvhCollisionMesh createBvhMesh(Node node) {
        try {
            GeometryExtractor geometryExtractor = GeometryExtractor.extractInWorldSpace(node);
            return new BvhCollisionMesh(geometryExtractor.getCoords(), geometryExtractor.getIndices(), new Mat4());
        } catch (Exception ex) {
            ex.printStackTrace();
            throw new RuntimeException("Failed to load tub model");
        }
    }

    public static BranchGroup createJava3DModel() {
        return loadVrml(PATH).getSceneGroup();
    }

    public static Scene loadVrml(String path) {
        try {
            return PluggableLoader.load(new File(path).toURI().toURL());
        } catch (Exception ex) {
            ex.printStackTrace();
            throw new RuntimeException("Failed to load model: " + path);
        }
    }

    public static BBox getBBox() {
        return new BBox(BoundingBoxHelper.getBoundingBox(loadVrml(PATH).getSceneGroup()));
    }
}
